package com.onlineauction.entities;

import java.util.Map;

import net.sf.jsr107cache.Cache;

import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.onlineauction.exceptions.UsernameAlreadyExistsException;
import com.onlineauction.exceptions.WrongPasswordException;
import com.onlineauction.helpers.CacheHandler;
import com.onlineauction.helpers.Constants;
import com.onlineauction.helpers.Constants.Usertype;

public class User extends GenericEntity {

	private String username;
	private String password;
	private Usertype usertype = Usertype.SELLER;
	private Map<String, Object> userinfo = null;

	public User(String username, Usertype usertype, Map<String, Object> userinfo, boolean toCreate)
			throws UsernameAlreadyExistsException {
		this.username = username;
		this.usertype = usertype;
		this.userinfo = userinfo;
		if (toCreate) {
			if (isUsernameAvailable(this.username)) {
				this.createAndStoreUserEntity();
			} else {
				throw new UsernameAlreadyExistsException();
			}
		}
	}

	@SuppressWarnings("unchecked")
	public User(String username, String password) throws WrongPasswordException {
		Entity entity = getEntity(Constants.USER, username);
		if (entity == null) {
			throw new WrongPasswordException();
		}
		if (!password.equals((String) entity.getProperty(Constants.PASSWORD))) {
			throw new WrongPasswordException();
		}

		this.password = (String) entity.getProperty(Constants.PASSWORD);
		this.usertype = (Usertype) entity.getProperty(Constants.USERTYPE);
		this.userinfo = (Map<String, Object>) entity.getProperty(Constants.USERINFO);
	}

	@SuppressWarnings("unchecked")
	public User(String username) {
		Entity entity = getEntity(Constants.USER, username);

		if (entity != null) {
			this.password = (String) entity.getProperty(Constants.PASSWORD);
			this.usertype = (Usertype) entity.getProperty(Constants.USERTYPE);
			this.userinfo = (Map<String, Object>) entity.getProperty(Constants.USERINFO);
		}
	}

	private Entity createAndStoreUserEntity() {
		Entity userEntity = new Entity(Constants.USER, username);
		userEntity.setProperty(Constants.USERTYPE, usertype);
		userEntity.setProperty(Constants.USERINFO, userinfo);
		userEntity.setProperty(Constants.PASSWORD, password);

		storeEntity(userEntity);
		return userEntity;
	}

	/**
	 * 
	 * @param username
	 * @return true if username is available (the username will be marked
	 *         unavailable subsequently for a certain period of time until being
	 *         made permanent) false if username is not available
	 */
	public static boolean isUsernameAvailable(String username) {
		if (username == null || username.length() == 0) {
			return false;
		}

		Key key = KeyFactory.createKey("user", username);
		String keyString = KeyFactory.keyToString(key);

		Cache usernameCache = CacheHandler.getUsernameCache();
		if (usernameCache != null) {
			if (usernameCache.containsKey(keyString)) {
				return false;
			}
		}

		Entity entity = getEntity(Constants.USER, username);
		if (entity == null) {
			return true;
		} else {
			return false;
		}
	}

	public String getUsername() {
		return username;
	}

	public String getPassword() {
		return password;
	}

	public Usertype getUsertype() {
		return usertype;
	}

	public Map<String, Object> getUserinfo() {
		return userinfo;
	}
	
	

}
